package lab4;


import com.alibaba.fastjson.JSONObject;

import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;

public class EBank {

    HashMap<String,EBankAccount> eBankAccountMap = new HashMap<>();
    private static EBank eBank;//单例
    private EBank(){

    }

    public static EBank Instance(){
        if(eBank == null){
            eBank = new EBank();
        }
        return eBank;
    }

    //设置密钥对
    private KeyPair setCustomerKP() throws NoSuchAlgorithmException {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(512);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        return keyPair;
    }

    //生成密钥
    public void setRSAKey(EBankAccount EBankAccount) throws NoSuchAlgorithmException {
        KeyPair kp = setCustomerKP();
        EBankAccount.setRsaKey((RSAPublicKey)kp.getPublic(), (RSAPrivateKey)kp.getPrivate());
    }


//    //验证签名
//    public boolean checkSignature(EBankAccount EBankAccount, byte[] sgn) throws NoSuchAlgorithmException,
//            InvalidKeySpecException, InvalidKeyException, SignatureException{
//        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(EBankAccount.getRsaPublicKey().getEncoded());
//        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
//        PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
//        Signature signature = Signature.getInstance("MD5withRSA");
//        signature.initVerify(publicKey);
//        signature.update(EBankAccount.getAccount().getBytes());
//        return signature.verify(sgn);
//    }


    //注册EBankAccount
    public void register(String account, String password, RSAPublicKey clientRSAPublicKey) throws NoSuchAlgorithmException {
        if (!eBankAccountMap.containsKey(account)){
            EBankAccount eBankAccount = new EBankAccount(account, password, clientRSAPublicKey);
            eBank.setRSAKey(eBankAccount);
            eBankAccountMap.put(account,eBankAccount);
        }else{
            System.out.println("用户已注册过电子银行");
        }
    }

    //验证签名
    public boolean checkSignature(String account, byte[] sgn) throws NoSuchAlgorithmException,
            InvalidKeySpecException, InvalidKeyException, SignatureException{
        EBankAccount eBankAccount = eBankAccountMap.get(account);
        if(eBankAccount == null){
            return false;
        }
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(eBankAccount.getClientRSAPublicKey().getEncoded());
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
        Signature signature = Signature.getInstance("MD5withRSA");
        signature.initVerify(publicKey);
        signature.update(eBankAccount.getPassword().getBytes());
        return signature.verify(sgn);
    }

    public boolean withdrawHelp(JSONObject jsonObject) throws NoSuchAlgorithmException, InvalidKeySpecException, SignatureException, InvalidKeyException {
        String account = jsonObject.getString("account");
        if(!checkSignature(account, jsonObject.getBytes("password"))){
            System.out.println("密码错误");
            return false;
        }
        Integer money = jsonObject.getInteger("money");
        EBankAccount eBankAccount = eBankAccountMap.get(account);
        eBankAccount.withdraw(money);
        return true;
    }

    public boolean depositHelp(JSONObject jsonObject) throws NoSuchAlgorithmException, InvalidKeySpecException, SignatureException, InvalidKeyException {
        String account = jsonObject.getString("account");
        if(!checkSignature(account, jsonObject.getBytes("password"))){
            System.out.println("密码错误");
            return false;
        }
        Integer money = jsonObject.getInteger("money");
        EBankAccount eBankAccount = eBankAccountMap.get(account);
        eBankAccount.deposit(money);
        return true;
    }


}
